import type { NitroFetchRequest } from 'nitropack'
import StorageUtil from '~/utils/storage'

// 存储键名
const ACCESS_TOKEN_KEY = 'access_token'
const REFRESH_TOKEN_KEY = 'refresh_token'

// 刷新状态
let isRefreshing = false
let refreshSubscribers: ((token: string) => void)[] = []

// 订阅刷新事件
const subscribeTokenRefresh = (cb: (token: string) => void) => {
  refreshSubscribers.push(cb)
}

// 发布新 Token
const onRefreshed = (token: string) => {
  refreshSubscribers.forEach(cb => cb(token))
  refreshSubscribers = []
}

export const useApi = <T>(url: NitroFetchRequest, options?: any) => {
  const { $toast } = useNuxtApp()

  const accessToken = StorageUtil.get<string>(ACCESS_TOKEN_KEY)
  const refreshToken = StorageUtil.get<string>(REFRESH_TOKEN_KEY)

  // 刷新 Token 的函数
  const refreshTokens = async () => {
    try {
      // 防止并发刷新
      if (isRefreshing) {
        return new Promise<string>((resolve) => {
          subscribeTokenRefresh(resolve)
        })
      }

      isRefreshing = true

      const response = await $fetch<{ accessToken: string }>('/api/auth/refresh', {
        method: 'POST',
        body: { refreshToken }
      })

      const newAccessToken = response.accessToken
      StorageUtil.set(ACCESS_TOKEN_KEY, newAccessToken)
      isRefreshing = false
      onRefreshed(newAccessToken)

      return newAccessToken
    } catch (error) {
      console.error('刷新 Token 失败:', error)
      isRefreshing = false
      refreshSubscribers = []

      // 清除所有 token，跳转到登录
      StorageUtil.remove(ACCESS_TOKEN_KEY)
      StorageUtil.remove(REFRESH_TOKEN_KEY)
      navigateTo('/login')

      throw error
    }
  }

  return $fetch<T>(url, {
    ...options,
    headers: {
      ...(accessToken ? { Authorization: `Bearer ${accessToken}` } : {}),
      ...options?.headers,
    },
    async onResponseError({ response }) {
      const status = response?.status || 500
      const message = response?._data?.message || '请求失败'

      // 401 错误处理：尝试刷新 Token
      if (status === 401 && refreshToken) {
        try {
          const newAccessToken = await refreshTokens()

          // 使用新 Token 重试原请求
          const retryResponse = await $fetch<T>(url, {
            ...options,
            headers: {
              ...options?.headers,
              Authorization: `Bearer ${newAccessToken}`
            }
          })

          return retryResponse
        } catch (refreshError) {
          console.error('刷新 Token 后重试失败:', refreshError)
        }
      }

      // 其他错误处理保持不变
      switch (status) {
        case 400:
          console.error('错误请求:', message)
          break
        case 401:
          console.error('未授权:', message)
          StorageUtil.remove(ACCESS_TOKEN_KEY)
          StorageUtil.remove(REFRESH_TOKEN_KEY)
          navigateTo('/login')
          break
        case 403:
          console.error('禁止访问:', message)
          break
        case 404:
          console.error('未找到:', message)
          break
        case 500:
          console.error('服务器错误:', message)
          break
        default:
          console.error('未知错误:', message)
      }

      $toast.error(message || '发生错误!', { position: 'top-center' })
      throw response
    }
  })
}